#include "Task.hpp"

const int processnum = 10;
std::vector<task_t> tasks;

class channel
{
public:
    channel(int cmdfd, pid_t slaverid, const std::string &processname)
        : _cmdfd(cmdfd), _slaverid(slaverid), _processname(processname)
    {
    }

public:
    int _cmdfd;
    pid_t _slaverid;
    std::string _processname;
};
void slaver()
{

    while (true)
    {
        int rea = 0;

        ssize_t n = read(0, &rea, sizeof(int));
        if (n == sizeof(int))
        {
            std::cout << "child get message: " << getpid() << " code:" << rea << std::endl;
            if (rea >= 0 && rea < tasks.size())
                tasks[rea]();
        }
        if (n == 0)
            break;
    }
}
void InitProcessPool(std::vector<channel> *channels)
{
    std::vector<int> oldfds;
    for (int i = 0; i < processnum; i++)
    {
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        assert(!n);
        (void)n;
        pid_t id = fork();
        if (id == 0)
        {
            // child
            std::cout << "close fd:";
            for (auto i : oldfds)
            {
                std::cout << i << " ";
                close(i);
            }
            std::cout << std::endl;
            close(pipefd[1]);
            // slaver(pipefd[0]);
            dup2(pipefd[0], 0);
            slaver();
            std::cout << "child exit:" << getpid() << std::endl;
            exit(0);
        }
        // father
        close(pipefd[0]);
        std::string name = "process-" + std::to_string(i);
        channels->push_back(channel(pipefd[1], id, name));
        oldfds.push_back(pipefd[1]);
        sleep(1);
    }
}

void Debug(const std::vector<channel> &channels)
{
    for (const auto &iter : channels)
    {
        std::cout << iter._cmdfd << ":" << iter._slaverid << ":" << iter._processname << std::endl;
    }
}
void Menu()
{
    std::cout << "*******************" << std::endl;
    std::cout << "****1.<1> 2.<2>****" << std::endl;
    std::cout << "****3.<3> 4.<4>****" << std::endl;
    std::cout << "******0.exit*******" << std::endl;
    std::cout << "*******************" << std::endl;
}

void ctrlprocess(const std::vector<channel> &channels)
{
    // for (int i = 0; i < 100; i++)
    int cnt = 0;
    while (true)
    {
        int select = 0;
        Menu();
        std::cout << "please cin:";
        std::cin >> select;
        if (select == 0)
            break;
        int cmdcode = select - 1;
        // int cmdcode = rand() % tasks.size();
        //  int processpos = rand() % channels.size();//随机数
        write(channels[cnt]._cmdfd, &cmdcode, sizeof(int));
        std::cout << "father sent to message:" << getpid()
                  << " code:" << cmdcode << " " << channels[cnt]._cmdfd << ":"
                  << channels[cnt]._slaverid << std::endl;
        sleep(1);
        cnt++; // 轮询
        cnt %= channels.size();
    }
}
void Cend(const std::vector<channel> &channels)
{
    int last = channels.size() - 1;

    // for (int i = last; i >= 0; i--)
    // {
    //     close(channels[i]._cmdfd);
    //     waitpid(channels[i]._slaverid, nullptr, 0);
    // }
    for (int i = 0; i < channels.size(); i++)
    {
        close(channels[i]._cmdfd);
        waitpid(channels[i]._slaverid, nullptr, 0);
    }
    // sleep(5);
    //  for (int i = 0; i < channels.size(); i++)
    //  {
    //      waitpid(channels[i]._slaverid, nullptr, 0);
    //  }
    // sleep(5);
}

int main()
{

    LoadTask(&tasks);

    srand(time(nullptr) ^ 1023);
    std::vector<channel> channels;
    // 1初始化
    InitProcessPool(&channels);

    // // test
    // Debug(channels);

    // 2 开始控制子进程
    ctrlprocess(channels);

    // 3清理收尾
    Cend(channels);
    return 0;
}